#ifndef CST816D_H
#define CST816D_H

#include <stdbool.h>
#include <stdint.h>

#define CST816D_REG_GESTURE_ID        0x01 // 手势寄存器
#define CST816D_REG_FINGER_NUM        0x02 // 手指数量
#define CST816D_REG_XPOS_HIGH         0x03 // X坐标高四位
#define CST816D_REG_XPOS_LOW          0x04 // X坐标低八位
#define CST816D_REG_YPOS_HIGH         0x05 // Y坐标高四位
#define CST816D_REG_YPOS_LOW          0x06 // Y坐标低八位
#define CST816D_REG_WORK_MODE         0xA5 // 工作模式
#define CST816D_REG_CHIP_ID           0xA7 // 芯片型号
#define CST816D_REG_VENDOR_ID         0xA8 // 厂商型号
#define CST816D_REG_FW_VERSION        0xA9 // 固件版本
#define CST816D_REG_MOTION_MASK       0xEC // 触发动作
#define CST816D_REG_AUTOSLEEP_TIME    0xF9 // 自动休眠
#define CST816D_REG_IRQ_CTRL          0xFA // 中断控制
#define CST816D_REG_AUTO_RESET        0xFB // 无手势休眠
#define CST816D_REG_LONGPRESS_TIME    0xFC // 长按休眠
#define CST816D_REG_DISABLE_AUTOSLEEP 0xFE // 使能低功耗模式

#define CST816D_GESTURE_NONE       0x00
#define CST816D_GESTURE_SLIDEDOWN  0x01
#define CST816D_GESTURE_SLIDEUP    0x02
#define CST816D_GESTURE_SLIDELEFT  0x03
#define CST816D_GESTURE_SLIDERIGHT 0x04
#define CST816D_GESTURE_SINGLETAP  0x05
#define CST816D_GESTURE_DOUBLETAP  0x0B
#define CST816D_GESTURE_LONGPRESS  0x0C

#define CST816D_GESTURE_STR(v)                                \
	(v == CST816D_GESTURE_NONE)             ? "NONE"      \
	    : (v == CST816D_GESTURE_SLIDEUP)    ? "UP"        \
	    : (v == CST816D_GESTURE_SLIDEDOWN)  ? "DOWN"      \
	    : (v == CST816D_GESTURE_SLIDELEFT)  ? "LEFT"      \
	    : (v == CST816D_GESTURE_SLIDERIGHT) ? "RIGHT"     \
	    : (v == CST816D_GESTURE_SINGLETAP)  ? "SINGLE"    \
	    : (v == CST816D_GESTURE_DOUBLETAP)  ? "DOUBLE"    \
	    : (v == CST816D_GESTURE_LONGPRESS)  ? "LONGPRESS" \
	                                        : "UNKNOW"

#define CST816D_I2C_7BIT_ADDR 0x15

#ifndef LOW
#define LOW 0
#endif

#ifndef HIGH
#define HIGH 1
#endif

/**
 * @brief CST916D
 */
struct cst816d {
	struct {
		// 固定参数指受物理因素限制的参数，无法修改的值
		struct {
			int width;
			int height;
			uint8_t slave_address;
		} fix;
		// 可变参数指的是可以根据使用场景指定的参数值
		struct {
			int dummy;
		} var;
	} cfg;
	struct {
		int (*read)(uint8_t reg, uint8_t* bytes, uint32_t len);
		int (*write)(uint8_t reg, uint8_t* bytes, uint32_t len);
		void (*msleep)(int ms);
		void (*reset)(int val);
	} ops;
};

int cst816d_init(struct cst816d* tp);
int cst816d_sleepin(struct cst816d* tp);
int cst816d_wakeup(struct cst816d* tp);
int cst816d_get_info(struct cst816d* tp, uint8_t* chip, uint8_t* vendor, uint8_t* version);
int cst816d_get_coord(struct cst816d* tp, bool* pressed, uint16_t* x, uint16_t* y);
int cst816d_get_gesture(struct cst816d* tp, uint8_t* gestrue, bool* pressed, uint16_t* x, uint16_t* y);
void cst816d_deinit(struct cst816d* tp);

#endif
